﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Pyramid
{
    class Haar:Multiresolution
    {
        public override ImageWithDetail DownSample(ImageWithDetail dimage)
        {
            int i, j;
            ImageWithDetail rimage = new ImageWithDetail(dimage);
            GImage image = rimage.TheImage;
            double[] r = new double[image.Depth];
            GImage FinalImage = new GImage(image.Width / 2, image.Height / 2);
            GImage DetailImage1 = new GImage(image.Width / 2, image.Height / 2);
            GImage DetailImage2 = new GImage(image.Width / 2, image.Height / 2);
            GImage DetailImage3 = new GImage(image.Width / 2, image.Height / 2);


            //apply the filter to the columns
            GImage RowImage = new GImage(image.Width / 2, image.Height);

            for (j = 0; j < image.Height; j++)
            {



                for (i = 0; i < image.Width; i += 2)
                {
                    //find the lower resulotion pixel value
                    r = Find_NewValue(image, new double[2] { 0.5, 0.5 }, new int[2] { i, j }, 0);
                    RowImage.SetPixel(i / 2, j, r);

                }

            }


            //Find the details
            GImage RowDetailImage = new GImage(image.Width / 2, image.Height);
            for (j = 0; j < image.Height; j++)
            {


                for (i = 0; i < image.Width; i += 2)
                {
                    //find the corresponding detail
                    r = Find_NewValue(image, new double[2] { 0.5, -0.5 }, new int[2] { i, j }, 0);
                    RowDetailImage.SetPixel(i / 2, j, r);

                }

            }


            //reduce the resolution in vertical direction
            for (i = 0; i < RowImage.Width; i++)
            {




                for (j = 0; j < RowImage.Height; j += 2)
                {
                    //find the lower resulotion pixel value
                    //the row image
                    r = Find_NewValue(RowImage, new double[2] { 0.5,0.5 }, new int[2] { i, j }, 1);
                    FinalImage.SetPixel(i, j / 2, r);
                    //the row detail image
                    r = Find_NewValue(RowDetailImage, new double[2] { 0.5,0.5 }, new int[2] { i, j }, 1);
                    DetailImage2.SetPixel(i, j / 2, r);


                }

            }

            //Find the details

            for (i = 0; i < RowImage.Width; i++)
            {


                for (j = 0; j < RowImage.Height; j += 2)
                {
                    //find the corresponding detail
                    //the row image
                    r = Find_NewValue(RowImage, new double[2] { 0.5, -0.5 }, new int[2] { i, j }, 1);
                    DetailImage1.SetPixel(i, j / 2, r);
                    //the row detail image
                    r = Find_NewValue(RowDetailImage, new double[2] { 0.5, -0.5 }, new int[2] { i, j }, 1);
                    DetailImage3.SetPixel(i, j / 2, r);


                }

            }



            rimage.TheImage = FinalImage;



            //save the details

            rimage.TheDetails.Add(Amp_Factor* DetailImage1);//the detail of the final image
            rimage.TheDetails.Add(Amp_Factor * DetailImage2);//the detail image of the row image
            rimage.TheDetails.Add(Amp_Factor * DetailImage3);//the detail of the detail image

            return rimage;
        }
        public override ImageWithDetail UpSample(ImageWithDetail dimage)
        {
            int i, j;
            double[] r1 = new double[dimage.TheImage.Depth];
            double[] r2 = new double[dimage.TheImage.Depth];
            GImage image = dimage.TheImage;
            GImage FinalImage = new GImage(image.Width * 2, image.Height * 2);

            //increase the resolution in horizontal direction
            GImage RowImage = new GImage(image.Width, image.Height * 2);
            GImage RowDetailImage = new GImage(image.Width, image.Height * 2);

            for (i = 0; i < image.Width; i++)
            {
                
                //the regular filters
                for (j = 0; j < image.Height; j++)
                {


                    
                    for (int k = 0; k < r2.Length; k++)
                        if (dimage.TheDetails.Count > 0)
                            r1[k] = image.data[i, j, k] + dimage.TheDetails[dimage.TheDetails.Count - 3].data[i,j,k];
                        else
                            r1[k] = image.data[i, j, k];
                    RowImage.SetPixel(i, 2 * j , r1);


                    for (int k = 0; k < r2.Length; k++)
                        if (dimage.TheDetails.Count > 0)
                            r1[k] = image.data[i, j, k] - dimage.TheDetails[dimage.TheDetails.Count - 3].data[i, j, k];
                        else
                            r1[k] = image.data[i, j, k];
                    RowImage.SetPixel(i, 2 * j + 1, r1);
                    if (dimage.TheDetails.Count > 0)
                    {
                        //do the same to find the detail row image
                    

                        for (int k = 0; k < r2.Length; k++)
                            r1[k] = dimage.TheDetails[dimage.TheDetails.Count - 2].data[i, j, k] + dimage.TheDetails[dimage.TheDetails.Count - 1].data[i,j,k];

                        RowDetailImage.SetPixel(i, 2 * j, r1);

                        for (int k = 0; k < r2.Length; k++)
                            r1[k] = dimage.TheDetails[dimage.TheDetails.Count - 2].data[i, j, k] - dimage.TheDetails[dimage.TheDetails.Count - 1].data[i, j, k];

                        RowDetailImage.SetPixel(i, 2 * j, r1);
                        RowDetailImage.SetPixel(i, 2 * j + 1, r1);
                    }
                    else
                    {
                        for (int k = 0; k < r2.Length; k++)
                            r1[k] = 0;

                        RowDetailImage.SetPixel(i, 2 * j , r1);
                        RowDetailImage.SetPixel(i, 2 * j + 1, r1);
                    }

                }
               

            }
            //increase the resolution in vertical direction
            for (j = 0; j < RowImage.Height; j++)
            {
             
                //regular filters
                for (i = 0; i < RowImage.Width; i++)
                {
                    for (int k = 0; k < r2.Length; k++)
                        r1[k] = RowImage.data[i, j, k] + RowDetailImage.data[i, j, k];

                   


                    FinalImage.SetPixel(2 * i, j, r1);


                    for (int k = 0; k < r2.Length; k++)
                        r1[k] = RowImage.data[i, j, k] - RowDetailImage.data[i, j, k];

                    FinalImage.SetPixel(2 * i + 1, j, r1);
                }
           
            }
            //remove the used details
            if (dimage.TheDetails.Count > 0)
            {
                dimage.TheDetails.RemoveAt(dimage.TheDetails.Count - 1);
                dimage.TheDetails.RemoveAt(dimage.TheDetails.Count - 1);
                dimage.TheDetails.RemoveAt(dimage.TheDetails.Count - 1);
            }
            dimage.TheImage = FinalImage;
            // dimage.TheImage = RowDetailImage;
            return dimage;
        }
    }
}
